package com.springboot.frame.config;

import com.springboot.frame.model.Content;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.ControlledRealTimeReopenThread;
import org.apache.lucene.search.SearcherFactory;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liheng
 * @ClassName LuceneConfig
 * @Description
 * @date 2021-03-15 11:37
 */
@Configuration
public class LuceneConfig {
    /**
     * lucene索引,存放位置
     */
    public static final String LUCENE_INDEX_PATH = "example/spring-boot-lucence/index/";

    /**
     * 索引数据
     */
    public static List<Content> INDEX_DATA = new ArrayList<>();

    /**
     * 添加索引数据
     */
    static {
        INDEX_DATA.add(new Content(1, "Java面向对象", "10", null, "Java面向对象从入门到精通,简单上手"));
        INDEX_DATA.add(new Content(2, "Java面向对象java", "10", null, "Java面向对象从入门到精通,简单上手"));
        INDEX_DATA.add(new Content(3, "Java面向编程", "15", null, "Java面向对象编程书籍"));
        INDEX_DATA.add(new Content(4, "JavaScript入门", "18", null, "JavaScript入门编程书籍"));
        INDEX_DATA.add(new Content(5, "深入理解Java编程", "13", null, "十三四天掌握Java基础"));
        INDEX_DATA.add(new Content(6, "从入门到放弃_Java", "20", null, "一门从入门到放弃的书籍"));
        INDEX_DATA.add(new Content(7, "Head First Java", "30", null, "《Head First Java》是一本完整地面向对象(object-oriented，OO)程序设计和Java的学习指导用书"));
        INDEX_DATA.add(new Content(8, "Java 核心技术：卷1 基础知识", "22", null, "全书共14章，包括Java基本的程序结构、对象与类、继承、接口与内部类、图形程序设计、事件处理、Swing用户界面组件"));
        INDEX_DATA.add(new Content(9, "Java 编程思想", "12", null, "本书赢得了全球程序员的广泛赞誉，即使是最晦涩的概念，在Bruce Eckel的文字亲和力和小而直接的编程示例面前也会化解于无形"));
        INDEX_DATA.add(new Content(10, "Java开发实战经典", "51", null, "本书是一本综合讲解Java核心技术的书籍，在书中使用大量的代码及案例进行知识点的分析与运用"));
        INDEX_DATA.add(new Content(11, "Effective Java", "10", null, "本书介绍了在Java编程中57条极具实用价值的经验规则，这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案"));
        INDEX_DATA.add(new Content(12, "分布式 Java 应用：基础与实践", "14", null, "本书介绍了编写分布式Java应用涉及的众多知识点，分为了基于Java实现网络通信、RPC;基于SOA实现大型分布式Java应用"));
        INDEX_DATA.add(new Content(13, "http权威指南", "11", null, "超文本传输协议(Hypertext Transfer Protocol，HTTP)是在万维网上进行通信时所使用的协议方案"));
        INDEX_DATA.add(new Content(14, "Spring", "15", null, "这是啥，还需要学习吗？Java程序员必备书籍"));
        INDEX_DATA.add(new Content(15, "深入理解 Java 虚拟机", "18", null, "作为一位Java程序员，你是否也曾经想深入理解Java虚拟机，但是却被它的复杂和深奥拒之门外"));
        INDEX_DATA.add(new Content(16, "springboot实战", "11", null, "完成对于springboot的理解，是每个Java程序员必备的姿势"));
        INDEX_DATA.add(new Content(17, "springmvc学习", "72", null, "springmvc学习指南"));
        INDEX_DATA.add(new Content(18, "vue入门到放弃", "20", null, "vue入门到放弃书籍信息"));
        INDEX_DATA.add(new Content(19, "vue入门到精通", "20", null, "vue入门到精通相关书籍信息"));
        INDEX_DATA.add(new Content(20, "vue之旅", "20", null, "由浅入深地全面介绍vue技术，包含大量案例与代码"));
        INDEX_DATA.add(new Content(21, "vue实战", "20", null, "以实战为导向，系统讲解如何使用 "));
        INDEX_DATA.add(new Content(22, "vue入门与实践", "20", null, "现已得到苹果、微软、谷歌等主流厂商全面支持"));
        INDEX_DATA.add(new Content(23, "Vue.js应用测试", "20", null, "Vue.js创始人尤雨溪鼎力推荐！Vue官方测试工具作者亲笔撰写，Vue.js应用测试完全学习指南"));
        INDEX_DATA.add(new Content(24, "PHP和MySQL Web开发", "20", null, "本书是利用PHP和MySQL构建数据库驱动的Web应用程序的权威指南"));
        INDEX_DATA.add(new Content(25, "Web高效编程与优化实践", "20", null, "从思想提升和内容修炼两个维度，围绕前端工程师必备的前端技术和编程基础"));
        INDEX_DATA.add(new Content(26, "Vue.js 2.x实践指南", "20", null, "本书旨在让初学者能够快速上手vue技术栈，并能够利用所学知识独立动手进行项目开发"));
        INDEX_DATA.add(new Content(27, "初始vue", "20", null, "解开vue的面纱"));
        INDEX_DATA.add(new Content(28, "什么是vue", "20", null, "一步一步的了解vue相关信息"));
        INDEX_DATA.add(new Content(29, "深入浅出vue", "20", null, "深入浅出vue，慢慢掌握"));
        INDEX_DATA.add(new Content(30, "三天vue实战", "20", null, "三天掌握vue开发"));
        INDEX_DATA.add(new Content(31, "不知火舞", "20", null, "不知名的vue"));
        INDEX_DATA.add(new Content(32, "娜可露露", "20", null, "一招秒人"));
        INDEX_DATA.add(new Content(33, "宫本武藏", "20", null, "我就是一个超级兵"));
        INDEX_DATA.add(new Content(34, "vue宫本vue", "20", null, "我就是一个超级兵"));
    }


    /**
     * 索引位置
     *
     * @return
     * @throws IOException
     */
    @Bean
    public Directory directory() throws IOException {
        Path path = Paths.get(LUCENE_INDEX_PATH);
        File file = path.toFile();
        if (!file.exists()) {
            //如果文件夹不存在,则创建
            file.mkdirs();
        }
        return FSDirectory.open(path);
    }

    /**
     * 创建一个 Analyzer 标准分詞器实例
     *
     * @return
     */
    @Bean
    public Analyzer standardAnalyzer() {
        return new StandardAnalyzer();
    }

    /**
     * 创建一个 Analyzer 中文分詞器实例
     *
     * @return
     */
    @Bean
    public Analyzer smartChineseAnalyzer() {
        return new SmartChineseAnalyzer();
    }


    /**
     * 创建indexWriter
     * 创建索引
     *
     * @return
     * @throws IOException
     */
    @Bean
    public IndexWriter indexWriter(Directory directory, Analyzer smartChineseAnalyzer) throws IOException {
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(smartChineseAnalyzer);
        // 设置打开方式：OpenMode.APPEND 会在索引库的基础上追加新索引。OpenMode.CREATE会先清空原来数据，再提交新的索引
        indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
        IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
        // 清空索引,应用重启会执行此方法
        // indexWriter.deleteAll();
        // indexWriter.commit();
        return indexWriter;
    }

    /**
     * SearcherManager管理
     *
     * @return
     * @throws IOException
     */
    @Bean
    public SearcherManager searcherManager(IndexWriter indexWriter) throws IOException {
        SearcherManager searcherManager = new SearcherManager(indexWriter, false, false, new SearcherFactory());
        ControlledRealTimeReopenThread cRTReopenThead = new ControlledRealTimeReopenThread(indexWriter, searcherManager,
                5.0, 0.025);
        cRTReopenThead.setDaemon(true);
        //线程名称
        cRTReopenThead.setName("更新IndexReader线程");
        // 开启线程
        cRTReopenThead.start();
        return searcherManager;
    }

}
